using Gameplay.PVE.Utils;
using LitJson;
using System;
using System.Collections.Generic;
using com.youzu.got.protocol;
using LogSystem;
using UnityEngine;
using WorldMapBase.Tile.Pool;
using XLua;
using Yoozoo.Managers.ResourceManagerV2.Runtime;
using Yoozoo.UI.YGUI;
using Object = UnityEngine.Object;
using UnityEngine.Profiling;
using Yoozoo.Gameplay.Liberty.AI.Node;

namespace Yoozoo.Gameplay.RTS
{
    /// <summary>
    /// 特效对象加载、缓存池
    /// </summary>
    public partial class RTSResourceManager
    {
        public enum EResourceType
        {
            SkillEffect = 1,
            SkillDirector = 2,
            Throwable = 3,
            MoveEffect = 4,
            RangeEffect = 5,
            soldierEffect = 6,
            SelectEffect = 7,
            UiEffect = 8,
            MarchSmoke = 9,
            SoldierThrowEffect = 10,
            HeroSkill = 110,
        }

        public static Material MarchMaterial;
        //private readonly Dictionary<string, Sprite> _heroIconCache = new Dictionary<string, Sprite>();
        //private readonly Dictionary<string, Sprite> _marchStateIconCache = new Dictionary<string, Sprite>();
        //private readonly Dictionary<string, Sprite> _parkIconCache = new Dictionary<string, Sprite>();
        //private readonly Dictionary<string, Sprite> _heroTypeIconCache = new Dictionary<string, Sprite>();
        //private readonly Dictionary<string, Sprite> _heroFrameIconCache = new Dictionary<string, Sprite>(4);
        //private readonly Dictionary<string, Sprite> _TeamColorIconCache = new Dictionary<string, Sprite>(4);
        private readonly Dictionary<string, Sprite> _rtsSpriteCache = new Dictionary<string, Sprite>(32);
        //private readonly Dictionary<int, Sprite> _flyTextBgCache = new Dictionary<int, Sprite>();
        private readonly Dictionary<string, Sprite> _flyIconTextCache = new Dictionary<string, Sprite>(16);
        private readonly Dictionary<string, Material> _rtsMatCache = new Dictionary<string, Material>(4);
        private readonly Dictionary<EResourceType, ResourcePool> _resourcePoolDic =
            new Dictionary<EResourceType, ResourcePool>();

        private Action _loadOver;

        private RTSModelManager _modelManager;
        private ResLoader _resLoader;
        private ResLoader _jsonResLoader;
        private Dictionary<int, TRtsResourceConfig> _resourceConfigDic;
        private Dictionary<int,Dictionary<int, THeroSkill>> _heroSkillConfig;
        private Dictionary<int, Dictionary<int, rts_quality_level>> _rts_quality_levelConfig;
        private Dictionary<int, Dictionary<int, rts_fomation_soldierIndex>> _rts_formation_soldierIndexConfig;
        private Dictionary<int, skill_element_rts> _skill_element_rts_config;
        private Dictionary<int,TRtsResourcePoolConfig> _resourcePoolConfigDic;
        private Dictionary<int, hero_monster> _hero_monster_Config;
        private Dictionary<string, string> _lang_Config = new Dictionary<string, string>();
        private Dictionary<int, RTSItemConfigData> _item_Config = new Dictionary<int, RTSItemConfigData>(); 
        private GameObject _resourcePoolRoot;
        private GameObject _root;

        private readonly Dictionary<int, SoldiersDataConfig>
            _soldierDataMap = new Dictionary<int, SoldiersDataConfig>();

        private readonly Dictionary<string, TRtsSoldierModelConfig> _soldierModelInfoDic =
            new Dictionary<string, TRtsSoldierModelConfig>();


        private static List<RtsPrefabPool> waitToLoadDynamic = new List<RtsPrefabPool>();
        /// <summary>
        /// 0=没有东西再加载，1=有东西在加载，2=有东西上一帧加载完了
        /// </summary>
        private int dynamicLoadState = 0;
        private bool isLoadComplete = false;
        private float startLoadDyanamicTime = 0;

        private RTSSpriteManager _spriteManager;
        public RtsJsonConfigManager JsonManager;
        public const string MARCHHUD_SPRITE_GRAY_MAT = "UI/Material/RTS_HUD_Materials/mat_AlphaZWriteOn_02_gray";//沙盘战斗时的玩家头像
        public const string MARCHHUD_SPRITE_Fill_MAT = "UI/Material/mat_SpriteZOffOverlayFill";
        public const string MARCHHUD_SPRITE_MAT = "UI/Material/RTS_HUD_Materials/mat_AlphaZWriteOn_LOD5";
        public const string MARCHHUD_LOD1_SPRITE_MAT = "UI/Material/RTS_HUD_Materials/mat_AlphaZWriteOn_LOD5";//沙盘LOD1时玩家的头像
        private const string PoliceSeigeEffect = "Assets/ResourcesAssets/Prefabs/Effect/Battle/Rts/Other/SeigeEffectPoint_policestation.prefab";
        private const string BossDeadEffect = "Assets/ResourcesAssets/Prefabs/Effect/Battle/Rts/Other/sfx_rts_machine01_Deathexplosion.prefab";
        public void Init(Transform parent)
        {
            if (_root != null)
            {
                Object.Destroy(_root);
            }

            _resLoader = ResLoader.Alloc();
            _root = new GameObject("[RTSResourceManager]");
            _root.transform.parent = parent;
            _root.SetActive(false);
            if (_resourcePoolRoot != null)
            {
                Object.Destroy(_resourcePoolRoot);
            }

            _resourcePoolRoot = new GameObject("RTSResourcePool");
            _resourcePoolRoot.transform.parent = parent;
            _resourcePoolRoot.transform.localPosition = new Vector3(-999, 0, -999);
            _spriteManager = new RTSSpriteManager();
            _spriteManager.Init();
            _modelManager = new RTSModelManager(_resLoader);
        }


        public void LoadBattlePrefabs(Action loadOver)
        {
            _loadOver = loadOver;
            _modelManager.Init(_root.transform);
            InitJsonConfigManager(() => { InitResource(_loadOver); });
        }

        internal void PreloadResourceConfig(LuaTable resourceConfig, LuaTable resourcePoolConfig)
        {
            PveUtils.PreloadRpgConfig<TRtsResourceConfig>(resourceConfig, ref _resourceConfigDic);
            PveUtils.PreloadRpgConfig<TRtsResourcePoolConfig>(resourcePoolConfig, ref _resourcePoolConfigDic);
        }

        internal void PreloadSkillConfig(LuaTable hero_skillConfig, LuaTable skill_element_rts_config,LuaTable hero_monsterConfig)
        {
            Profiler.BeginSample("PreloadRpgConfigWithSubKey");
            PveUtils.PreloadRpgConfigWithSubKey<THeroSkill>(hero_skillConfig, ref _heroSkillConfig,"id","skill_level");
            Profiler.EndSample();
            Profiler.BeginSample("_skill_element_rts_config");
            PveUtils.PreloadRpgConfig<skill_element_rts>(skill_element_rts_config, ref _skill_element_rts_config);
            Profiler.EndSample();
            Profiler.BeginSample("_hero_monster_Config");
            PveUtils.PreloadRpgConfig<hero_monster>(hero_monsterConfig, ref _hero_monster_Config);
            Profiler.EndSample();
        }
        internal void PreloadQualityLevelConfig(LuaTable rts_quality_levelConfig)
        {
            PveUtils.PreloadRpgConfigWithSubKey<rts_quality_level>(rts_quality_levelConfig, ref _rts_quality_levelConfig, "id", "quality");
        }
        
        public void PreloadFormationSoldierPositionCfg(LuaTable formationSoldierPositionCfg)
        {
            PveUtils.PreloadRpgConfigWithSubKey<rts_fomation_soldierIndex>(formationSoldierPositionCfg, ref _rts_formation_soldierIndexConfig, "id", "sid");
        }
        internal void PreloadRTSNeedLangConfig(LuaTable table)
        {
            for (int i = 1; i <= table.Length; i++)
            {
                var item = table.Get<int, LuaTable>(i);
                var key = item.Get<string, string>("key");
                var value = item.Get<string, string>("value");
                _lang_Config[key] = value;
            }
        }

        internal void PreloadRTSNeedItemConfig(LuaTable table) 
        {
            for (int i = 1; i <= table.Length; i++)
            {
                var info = table.Get<int, LuaTable>(i);
                if (info != null)
                {
                    int id = GetInt(info, "id");
                    string name = (string)info["name"];
                    int type = GetInt(info, "type");
                    int quality = GetInt(info, "quality");
                    string icon = (string)info["icon"];

                    RTSItemConfigData config = new RTSItemConfigData();
                    config.name = name;
                    config.type = type;
                    config.quality = quality;
                    config.icon = icon;
                    _item_Config[id] = config;

                }
            }

        }


        public rts_quality_level GetRTSQualityLevelConfig(int id,int quality)
        {
            if (_rts_quality_levelConfig.TryGetValue(id,out var dic))
            {
                if (dic.TryGetValue(quality,out var rts_quality))
                {
                    return rts_quality;
                }
            }
            return null;
        }
        public string GetLangConfigTxt(string id)
        {
            if (_lang_Config.TryGetValue(id, out var str))
            {
                return str;
            }
            return string.Empty;
        }
        public hero_monster GetHeroMonsterConig(int heroId)
        {
            if (_hero_monster_Config.TryGetValue(heroId, out var hero_monster))
            {
                return hero_monster;
            }
            return null;
        }

        public THeroSkill GetHeroSkillConfig(int skillId,int skillLevel)
        {
            if (_heroSkillConfig.TryGetValue(skillId,out var dic))
            {
                if (dic.TryGetValue(skillLevel,out var heroSkill))
                {
                    return heroSkill;
                }
            }
            return null;
        }

        public skill_element_rts GetSkillElementRtsConfig(int elementId)
        {
            if (_skill_element_rts_config.TryGetValue(elementId, out var skill_element_rts))
            {
                return skill_element_rts;
            }
            return null;
        }

        public void TryLoadResource(int id)
        {
            if (_resourceConfigDic.TryGetValue(id, out var config))
            {
                var resourcePool = _resourcePoolDic[(EResourceType) config.type];
                resourcePool.TryLoadResource(id);
            }
        }

        public GameObject GetResourceById(int id, bool isForceGet = false,Action<GameObject> action = null)
        {
            if (_resourceConfigDic.TryGetValue(id, out var config))
            {
                var obj = _resourcePoolDic[(EResourceType) config.type].GetResource(id, isForceGet,action);

                return obj;
            }

            return null;
        }

        public void RecoverResourceById(int id, GameObject obj)
        {
            if (_resourceConfigDic.TryGetValue(id, out var config))
            {
                obj.transform.SetParent(_resourcePoolRoot.transform);
                _resourcePoolDic[(EResourceType) config.type].RecoverResource(id, obj);
            }
        }

        public void SetSpriteByPath(string path,YImage yImage)
        {
            if (_rtsSpriteCache.TryGetValue(path,out Sprite sprite))
            {
                yImage.sprite = sprite;
                return;
            }

            _resLoader.Add2Load(path, typeof(Sprite), (success, name, asset) =>
            {
                var loadedSprite = asset as Sprite;
                if (success && loadedSprite != null)
                {
                    _rtsSpriteCache[path] = loadedSprite;
                    yImage.sprite = loadedSprite;
                }
            }).Load();
        }
        public void SetSpriteByPath(string path, SpriteRenderer spriteRenderer)
        {
            if (_rtsSpriteCache.TryGetValue(path, out Sprite sprite))
            {
                spriteRenderer.sprite = sprite;
                return;
            }

            _resLoader.Add2Load(path, typeof(Sprite), (success, name, asset) =>
            {
                var loadedSprite = asset as Sprite;
                if (success && loadedSprite != null)
                {
                    _rtsSpriteCache[path] = loadedSprite;
                    spriteRenderer.sprite = loadedSprite;
                }
            }).Load();
        }
        public void SetHeroIcon(string icon, YImage image)
        {
            SetHeroRtsAtlasIcon(icon, image);
        }

        public void SetHeroTypeIcon(string icon, YImage image)
        {
            SetHeroRtsAtlasIcon(icon, image);
        }
        public void SetHeroTypeIcon(string icon, SpriteRenderer render)
        {
            SetHeroRtsAtlasIcon(icon, render);
        }
        public void SetMarchStateIcon(string icon, YImage image)
        {
            SetHeroRtsAtlasIcon(icon, image);
        }

        public void SetParkIcon(string icon, YImage image)
        {
            SetHeroRtsAtlasIcon(icon, image);
        }

        internal void SetRaderQualityIcon(SpriteRenderer qualityImage, string image)
        {
            SetHeroRtsAtlasIcon(image,qualityImage);
        }

        public void SetRadarBottomIconByTypeAndQuality(int type, int quality, SpriteRenderer qualityImage)
        {
            string iconPath = string.Format("img_radar_markerNew_0{0}_0{1}", type, quality);

            SetHeroRtsAtlasIcon(iconPath, qualityImage);
        }

        public void SetRadarEventIcon(int type, int id, YImage image) 
        {
            string iconPath = "";
            //item物品
            if (type == 2) 
            {
                iconPath = GetItemIconPath(id);
            }
            //soldier
            else if (type == 3)
            {
                iconPath= GetSoldierHeadIcon(id);
            }
    
            SetSpriteByPath(iconPath, image);

        }

        public void SetRadarEventIconWithRelativePath(string relativePath, SpriteRenderer image) 
        {
            string iconPath = $"Assets/ResourcesAssets/{relativePath}.png";
            SetSpriteByPath(iconPath, image);
        } 

        public void SetHeadFrameIcon(string icon, YImage spriteRenderer)
        {
            SetHeroRtsAtlasIcon(icon, spriteRenderer);
        }

        public void SetTeamColorIcon(string icon, SpriteRenderer spriteRenderer)
        {
            SetHeroRtsAtlasIcon(icon, spriteRenderer);
        }

        public void SetHeroRtsAtlasIcon(string icon, SpriteRenderer spriteRenderer)
        {
            if(string.IsNullOrEmpty(icon))
            {
                Debug.LogError(LogModule.RTS, "SetHeroRtsAtlasIcon: icon is null");
                return;
            }
            
            string iconPath = $"Assets/ResourcesAssets/UI/GUI/heroRts/{icon}.png";
            SetSpriteByPath(iconPath, spriteRenderer);
        }
        
        public void SetHeroRtsAtlasIcon(string icon, YImage yImage)
        {
            if(string.IsNullOrEmpty(icon))
            {
                Debug.LogError(LogModule.RTS, "SetHeroRtsAtlasIcon: icon is null");
                return;
            }
            
            string iconPath = $"Assets/ResourcesAssets/UI/GUI/heroRts/{icon}.png";
            SetSpriteByPath(iconPath, yImage);
        }

        public void SetAllianceIcon(string icon, YImage yImage)
        {
            if (string.IsNullOrEmpty(icon))
            {
                yImage.sprite = null;
                return;
            }
            string iconPath = $"Assets/ResourcesAssets/{icon}.png";
            SetSpriteByPath(iconPath, yImage);
        }
        public void SetWorldmapAtlasIcon(string icon, YImage yImage)
        {
            string iconPath = $"Assets/ResourcesAssets/UI/GUI/worldmap/{icon}.png";
            SetSpriteByPath(iconPath, yImage);
        }
        public void SetWorldmapAtlasIcon(string icon, SpriteRenderer spriteRenderer)
        {
            string iconPath = $"Assets/ResourcesAssets/UI/GUI/worldmap/{icon}.png";
            SetSpriteByPath(iconPath, spriteRenderer);
        }
        
        public void SetMapElementAtlasIcon(string icon, SpriteRenderer spriteRenderer)
        {
            string iconPath = $"Assets/ResourcesAssets/UI/GUI/mapelement/{icon}.png";
            SetSpriteByPath(iconPath, spriteRenderer);
        }
        
        public void SetAtlasIcon(string icon, SpriteRenderer spriteRenderer)
        {
            string iconPath = $"Assets/ResourcesAssets/{icon}.png";
            SetSpriteByPath(iconPath, spriteRenderer);
        }
        
        public void SetFlyTextBg(int team, SpriteRenderer image)
        {
            var iconPath = team == 0 || team == 1
               ? "Assets/ResourcesAssets/UI/GUI/heroRts/img_rts_base_skill02.png"
               : "Assets/ResourcesAssets/UI/GUI/heroRts/img_rts_base_skill01.png";
            SetSpriteByPath(iconPath, image);
        }

        public string GetSoldierHeadIcon(int id)
        {
            string iconPath = string.Empty;
            if (_soldierDataMap.TryGetValue(id, out var model))
            {
                string iconName = model.displayhead;
                iconPath = $"Assets/ResourcesAssets/UI/GUI/icon/soldier/{iconName}.png";
            }

            return iconPath;
        }


        public string GetItemIconPath(int id)
        {
            string iconPath = string.Empty;
            if (_item_Config.TryGetValue(id, out var cfg))
            {
                string iconName = cfg.icon;
                if (cfg.type == 5) //英雄技能专属道具
                {
                    iconPath = $"Assets/ResourcesAssets/UI/GUI/icon/heroSkillItem/{iconName}.png";
                }
                else if (cfg.type == 19) //皮肤 
                {
                    iconPath = $"Assets/ResourcesAssets/UI/GUI/icon/Skin/{iconName}.png";
                }
                else if (cfg.type == 15)  //增益道具
                {
                    iconPath = $"Assets/ResourcesAssets/UI/GUI/icon/itemBuff/{iconName}.png";
                }
                else
                {
                    iconPath = $"Assets/ResourcesAssets/UI/GUI/icon/item/{iconName}.png";
                }

            }

            return iconPath;
        }


        
        public void SetCarFlyTextBg(int team, SpriteRenderer image)
        {
            var iconPath = team == 0 || team == 1
                ? "Assets/ResourcesAssets/UI/GUI/heroRts/img_rts_base_carskill02.png"
                : "Assets/ResourcesAssets/UI/GUI/heroRts/img_rts_base_carskill01.png";
            SetSpriteByPath(iconPath, image);
        }

        public void SetCarFlyTextIcon(string icon, SpriteRenderer image)
        {
            if (string.IsNullOrEmpty(icon))
            {
                return;
            }

            string path = string.Format("Assets/ResourcesAssets/UI/GUI/icon/carSkill/{0}.png", icon);
            SetSpriteByPath(path, image);
        }

        public void SetFlyTextIcon(string icon, SpriteRenderer image)
        {
            if (_flyIconTextCache.TryGetValue(icon, out Sprite sprite))
            {
                image.sprite = sprite;
                return;
            }

            _resLoader.Add2Load($"Assets/ResourcesAssets/{icon}.png", typeof(Sprite), (success, name, asset) =>
            {
                var loadedSprite = asset as Sprite;
                if (success && loadedSprite != null)
                {
                    _flyIconTextCache[icon] = loadedSprite;
                    image.sprite = loadedSprite;
                }
            }).Load();
        }

        public void LoadMaterial(string path, YImage spriteRenderer,Action action = null)
        {
            string finalPath = $"Assets/ResourcesAssets/{path}.mat";
            if (_rtsMatCache.TryGetValue(finalPath,out var material))
            {
                spriteRenderer.material = material;
                action?.Invoke();
            }
            else
            {
                _resLoader.Add2Load(finalPath, (success, name, asset) =>
                {
                    var mat = asset as Material;
                    if (success && mat != null)
                    {
                        _rtsMatCache[finalPath] = mat;
                        spriteRenderer.material = mat;
                        action?.Invoke();
                    }
                }).Load();
            }
        }

        public void LoadSoldiers(Action onLoadOver)
        {
            _resLoader.Add2Load("Assets/ResourcesAssets/FrameAnimation/mat_rts_march.mat",
                (success, name, asset) =>
                {
                    MarchMaterial = UnityEngine.Object.Instantiate((Object) asset) as Material;
                    _spriteManager.LoadSoldiers(this, onLoadOver);
                }).Load();
        }

        public void LoadModel(string path,Action<GameObject> onLoadOver)
        {
            _resLoader.Add2Load(path, (success, name, asset) =>
            {
                var gameObject = UnityEngine.Object.Instantiate((Object)asset) as GameObject;
                onLoadOver.Invoke(gameObject);
            }).Load();
        }

        public void RemoveModel(IModel model)
        {
            if (BattleUtils.IsSprite)
            {

            }
            else
            {
                _modelManager.RemoveModel(model);
            }

        }

        public IModel GetModel(int index)
        {
            return _modelManager.GetModel(index);
        }

        public IModel GetModel(string modelName)
        {
            return _modelManager.GetModel(modelName);
        }

        public void Dispose()
        {
            _spriteManager.Dispose();
            foreach (var item in _resourcePoolDic.Values)
            {
                item.Dispose();
            }

            _modelManager.Dispose();
            Object.DestroyImmediate(_root);
            _root = null;
            Object.DestroyImmediate(_resourcePoolRoot);
            _resourcePoolRoot = null;
            JsonManager.Dispose();
            if (_resLoader != null)
            {
                _resLoader.Recycle2Cache();
                _resLoader = null;
            }

            if (_jsonResLoader != null)
            {
                _jsonResLoader.Recycle2Cache();
                _jsonResLoader = null;
            }

            startLoadDyanamicTime = 0;
            dynamicLoadState = 0;
            waitToLoadDynamic.Clear();
        }

        public void Update()
        {
            if (dynamicLoadState == 0)
            {
                if (waitToLoadDynamic.Count > 0)
                {
                    dynamicLoadState = 1;
                    startLoadDyanamicTime = Time.time;
                    var pool = waitToLoadDynamic[0];
                    pool.PreLoad((o) =>
                    {
                        dynamicLoadState = 2;
                    },true);
                    waitToLoadDynamic.RemoveAt(0);
                }
            }
            else if (dynamicLoadState == 1)
            {
                //容错，防止某一个回调回不来导致后面的加载都无效
                if (startLoadDyanamicTime > 0 && Time.time - startLoadDyanamicTime >= 5)
                {
                    startLoadDyanamicTime = 0;
                    dynamicLoadState = 2;
                }
            }
            else if (dynamicLoadState == 2)
            {
                dynamicLoadState = 0;
            }
        }

        private void InitResource(Action loadOver)
        {
            if (_resourcePoolConfigDic == null)
            {
                Debug.LogError("配置表初始化失败");
                return;
            }

            var enumarator = _resourcePoolConfigDic.GetEnumerator();
            while (enumarator.MoveNext())
            {
                var key = enumarator.Current.Key;
                var poolConfig = enumarator.Current.Value;
                if (!_resourcePoolDic.ContainsKey((EResourceType)poolConfig.id))
                {
                    ResourcePool pool = new ResourcePool();
                    pool.Initialize((EResourceType)poolConfig.id, _resourcePoolRoot.transform,
                        poolConfig.maxDynamicResourceNum, poolConfig.maxUseEffect);
                    _resourcePoolDic.Add((EResourceType)poolConfig.id, pool);
                }
            }
            enumarator.Dispose();

            var enumerator = _resourceConfigDic.GetEnumerator();
            while (enumerator.MoveNext())
            {
                var key = enumerator.Current.Key;
                var value = enumerator.Current.Value;

                _resourcePoolDic[(EResourceType) value.type].AddResource(value.id, value.name, value.poolNum,value.priority);
            }

            enumerator.Dispose();

            int totalCount = _resourcePoolDic.Count;
            int currentCount = 0;

            foreach (var item in _resourcePoolDic.Values)
            {
                item.StartLoading(() =>
                {
                    currentCount++;
                    ArmyManager.loadingCallBack?.Invoke(currentCount, totalCount, "resource");
                    if (currentCount == totalCount)
                    {

                        loadOver?.Invoke();
                    }
                });
            }


        }

        public void Log()
        {
            foreach (var pair in _resourcePoolDic)
            {
                var pool = pair.Value;
                string type = pair.Key.ToString();
                pool.Log(type);
            }
        }

        [BlackList]
        public Dictionary<string, TRtsSoldierModelConfig> GetSoldierModelInfoDic()
        {
            return _soldierModelInfoDic;
        }

      

        private void InitJsonConfigManager(Action onInitConfig)
        {
            _jsonResLoader = ResLoader.Alloc();
            JsonManager = RtsJsonConfigManager.GetInstance();
            JsonManager.LoadConfigAll(_jsonResLoader, onInitConfig);
        }

        public class ResourcePool
        {
            public ResLoader ResLoader;
            private readonly Dictionary<int, RtsPrefabPool> _objPoolDic = new Dictionary<int, RtsPrefabPool>();
            private Transform _root;
            private EResourceType _type;

            public void Initialize(EResourceType type, Transform root, int maxDynamicResourceNum = 10,
                int maxUseEffect = 10)
            {
                this._type = type;
                this._root = root;
            }

            public void AddResource(int id, string path, int poolNum,int priority)
            {
                if (!_objPoolDic.ContainsKey(id))
                {
                    RtsPrefabPool prefabPool =
                        new RtsPrefabPool(RTSQualityHelper.GetPoolInitNum(poolNum), poolNum,
                            $"Assets/ResourcesAssets/{path}.prefab", _root);
                    _objPoolDic[id] = prefabPool;
                    prefabPool.priority = priority;
                    prefabPool.loaded = false;
                }
            }

            public void TryLoadResource(int id)
            {
                if (_objPoolDic.TryGetValue(id, out var item))
                {
                    if (!item.loaded)
                    {
                        item.loaded = true;
                        waitToLoadDynamic.Add(item);
                        //item.PreLoad(null,true);
                    }
                }
            }
            
            public void StartLoading(Action loadOver)
            {
                int totalCount = _objPoolDic.Count;
                int currentCount = 0;
                foreach (var item in _objPoolDic.Values)
                {
                    if (item.priority == 1)
                    {
                        item.loaded = true;
                        item.PreLoad((o) =>
                        {
                            currentCount++;
                            if (currentCount == totalCount)
                            {
                                loadOver?.Invoke();
                            }
                        });
                    }
                    else
                    {
                        currentCount++;
                        if (currentCount == totalCount)
                        {
                            loadOver?.Invoke();
                        }
                    }
                }
            }


            public GameObject GetResource(int id, bool isForceGet = false,Action<GameObject> action = null)
            {
                RtsPrefabPool prefabPool;
                if (_objPoolDic.TryGetValue(id, out prefabPool))
                {
                    if (prefabPool.loaded)
                    {
                        return prefabPool.GetItem();
                    }
                    else
                    {
                        
                        prefabPool.PreLoad((obj) =>
                        {
                            action?.Invoke(obj);
                            prefabPool.loaded = true;
                        },true);
                    }
                }
                return null;
            }

            public void RecoverResource(int id, GameObject obj)
            {
                if (obj == null)
                {
                    return;
                }

                RtsPrefabPool prefabPool;
                if (_objPoolDic.TryGetValue(id, out prefabPool))
                {
                    prefabPool.RecoverItem(obj);
                }
            }


            public void Dispose()
            {
                foreach (var rtsPrefabPool in _objPoolDic)
                {
                    rtsPrefabPool.Value.Destroy();
                }

                _objPoolDic.Clear();
            }

            public void Log(string category)
            {
                int total = 0;
                foreach (var pair in _objPoolDic)
                {
                    var pool = pair.Value;
#if UWA
                    UWAEngine.LogValue(category + ": " + pool.Name, pool.AliveCount);
#endif
                    
                    total += pool.AliveCount;
                }
#if UWA
                UWAEngine.LogValue(category, total);
#endif
            }

        }

        [BlackList]
        public void LoadPoliceSeigeEffect(Action<GameObject> action)
        {
            _resLoader.Add2Load(PoliceSeigeEffect,(success, name, asset) =>
            {
                GameObject obj = Object.Instantiate((Object) asset) as GameObject;
                if (success)
                {
                    action?.Invoke(obj);
                }
            }).Load();
        }
        [BlackList]
        public void LoadBossDeadEffect(Action<GameObject> action)
        {
            _resLoader.Add2Load(BossDeadEffect, (success, name, asset) =>
            {
                GameObject obj = Object.Instantiate((Object)asset) as GameObject;
                if (success)
                {
                    action?.Invoke(obj);
                }
            }).Load();
        }
        

        [BlackList]
        public void PreloadSoldierConfig(LuaTable soldiers_dataConfig, LuaTable rts_soldier_model_configConfig)
        {
            for (int i = 1; i <= soldiers_dataConfig.Length; i++)
            {
                var info = soldiers_dataConfig.Get<int, LuaTable>(i);
                if (info != null)
                {
                    int id = GetInt(info, "id");
                    string model = (string) info["model"];
                    int soldierType = GetInt(info, "soldierType");
                    int AttackRange = GetInt(info, "attackRange");
                    string displayhead = (string)info["displayhead"];
                    SoldiersDataConfig config = new SoldiersDataConfig();
                    config.Model = model;
                    config.SoldierType = soldierType;
                    config.AttackRange = AttackRange;
                    config.displayhead = displayhead;
                    _soldierDataMap[id] = config;
                }
            }

            /*_soldierDataMap[0] = new SoldiersDataConfig()
            {
                Model = "gta_commander",
                SoldierType = 100
            };*/

            for (int i = 1; i <= rts_soldier_model_configConfig.Length; i++)
            {
                var info = rts_soldier_model_configConfig.Get<int, LuaTable>(i);
                if (info != null)
                {
                    int valid = GetInt(info,"valid");
                    if (valid == 1)
                    {
                        string id = (string) info["id"];
                        string model = (string) info["modelPath"];
                        string spritePath = (string) info["spritePath"];
                        float scale = GetFloat(info, "scale");
                        float shadowScale = GetFloat(info, "shadowScale");
                        float yoffset = GetFloat(info, "yoffset");
                        string selfColor = (string) info["selfColor"];
                        string friendColor = (string) info["friendColor"];
                        string enemyColor = (string) info["enemyColor"];
                        float[] shadowOffsetArray = GetFloatArray(info, "shadowOffset");
                        TRtsSoldierModelConfig config = new TRtsSoldierModelConfig();
                        config.id = id;
                        config.modelPath = model;
                        config.spritePath = spritePath;
                        config.scale = scale;
                        config.yoffset = yoffset;
                        config.selfColor = selfColor;
                        config.friendColor = friendColor;
                        config.enemyColor = enemyColor;
                        config.shadowScale = shadowScale;
                        config.shadowOffset = new Vector3(shadowOffsetArray[0], shadowOffsetArray[1], shadowOffsetArray[2]);
                        _soldierModelInfoDic[id] = config;
                        RTSModelManager.modelNameToIndex.Add(id, i);
                    }
                }
            }
            //RTSModelManager.modelNameToIndex["gta_commander"] = 100;
        }

        [BlackList]
        public string GetModelNameById(int id)
        {
            if (_soldierDataMap.TryGetValue(id, out var model))
            {
                return model.Model;
            }
            if (_soldierDataMap.TryGetValue(411011, out var model2))
            {
                return model2.Model;
            }
            return string.Empty;
        }

        [BlackList]
        public int GetSoldierAttackRangeById(int id)
        {
            if (_soldierDataMap.TryGetValue(id, out var model))
            {
                return model.AttackRange;
            }

            return 0;
        }

        [BlackList]
        public float GetModelScaleByName(string name)
        {
            if (_soldierModelInfoDic.TryGetValue(name, out var config))
            {
                return config.scale;
            }
            else
            {
                return 1;
            }
        }

        [BlackList]
        public string GetModelPathByName(string name)
        {
            if (_soldierModelInfoDic.TryGetValue(name, out var config))
            {
                return config.modelPath;
            }
            else if (name == "world_trade_train") // TODO 列车临时修改
            {
                return "Assets/ResourcesAssets/Prefabs/RTS/world_trade_train.prefab";
            }
            else
            {
                return "";
            }
        }
        private Dictionary<string, float> _soldierActionSpeed = new Dictionary<string, float>
        {
            ["gta_soilder_Batterer_1"] = 1f,
        };

        public float GetActionSpeedByName(string name)
        {
            if (_soldierActionSpeed.TryGetValue(name, out var speed))
            {
                return speed;
            }
            return 1;
        }

        [BlackList]
        public float GetModelShadowScaleByName(string name)
        {
            if (_soldierModelInfoDic.TryGetValue(name, out var config))
            {
                return config.shadowScale;
            }
            else
            {
                return 1;
            }
        }
        [BlackList]
        public float GetModelYOffsetByName(string name)
        {
            if (_soldierModelInfoDic.TryGetValue(name, out var config))
            {
                return config.yoffset;
            }
            else
            {
                return 0;
            }
        }

        [BlackList]
        public Vector3 GetModelShadowOffsetByName(string name)
        {
            if (_soldierModelInfoDic.TryGetValue(name, out var config))
            {
                return config.shadowOffset;
            }
            else
            {
                return Vector3.zero;
            }
        }

        [BlackList]
        public Color[][] GetColorByName(string name)
        {
            if (_soldierModelInfoDic.TryGetValue(name,out var config))
            {
                
                return new Color[][]
                {
                    GetColorsByCode(config.selfColor),
                    GetColorsByCode(config.friendColor),
                    GetColorsByCode(config.enemyColor),
                };
            }
            else
            {
                return new Color[][]
                {
                    new Color[]{Color.white,Color.white,Color.white},
                    new Color[]{Color.white,Color.white,Color.white},
                    new Color[]{Color.white,Color.white,Color.white},
                };
            }
        }

        private Color[] GetColorsByCode(string code)
        {
            var colorCodesArray = code.Split('|');
            Color[] results = new Color[3];
            for (int i = 0; i < colorCodesArray.Length; i++)
            {
                ColorUtility.TryParseHtmlString(colorCodesArray[i], out Color color);
                results[i] = color;
            }
            return results;
        }
        [BlackList]
        public int GetSoldierTypeById(int id)
        {
            if (_soldierDataMap.TryGetValue(id, out var model))
            {
                return model.SoldierType;
            }

            return 1;
        }

      

        private int GetInt(LuaTable table, string key)
        {
            return table.ContainsKey(key) ? table.Get<string, int>(key) : 0;
        }

        private float GetFloat(LuaTable table, string key)
        {
            return table.ContainsKey(key) ? table.Get<string, float>(key) : 0;
        }

        private float[] GetFloatArray(LuaTable table, string key)
        {
            return table.ContainsKey(key) ? table.Get<string, float[]>(key) : new float[] { 0,0,0};
        }

        

        public Dictionary<int, SoldiersDataConfig> SoldierDataMap => _soldierDataMap;

        public Dictionary<int, Dictionary<int, rts_fomation_soldierIndex>> Rts_formation_soldierIndexConfig =>
            _rts_formation_soldierIndexConfig;

    }
}
